package com.rayboo.example.java8;

import java.util.Optional;

/**
 * Optional 示例
 *
 * @author ray
 * @since 2019/07/29
 *
 * <p>在Java 8中，我们有一个新引入的Optional类java.util包。
 * 引入此类是为了避免在我们的代码中不执行空检查时经常遇到的NullPointerException。
 * 使用这个类，我们可以很容易地检查变量是否具有null值，通过这样做，我们可以避免NullPointerException。
 *
 * <p>https://beginnersbook.com/2017/10/java-8-optional-class/
 */
public class OptionalExample {

    public static void main(String[] args) {

        System.out.println("===== 不使用Optional类 =====");
        String[] strings = new String[10];
        //Getting the substring
//        String string = strings[9].substring(2, 5);
        //Displaying substring
//        System.out.print(string);

        System.out.println("===== 使用Optional类 =====");
        String[] str = new String[10];
        Optional<String> isNull = Optional.ofNullable(str[9]);
        if (isNull.isPresent()) {
            //Getting the substring
            String str2 = str[9].substring(2, 5);
            //Displaying substring
            System.out.print("Substring is: " + str2);
        } else {
            System.out.println("Cannot get the substring from an empty string");
        }
        str[9] = "AgraIsCool";
        Optional<String> isNull2 = Optional.ofNullable(str[9]);
        if (isNull2.isPresent()) {
            //Getting the substring
            String str2 = str[9].substring(2, 5);
            //Displaying substring
            System.out.print("Substring is: " + str2);
        } else {
            System.out.println("Cannot get the substring from an empty string");
        }

        System.out.println("===== Optional isPresent() vs ifPresent() methods =====");
        //Creating Optional object from a String
        Optional<String> GOT = Optional.of("Game of Thrones");
        //Optional.empty() creates an empty Optional object
        Optional<String> nothing = Optional.empty();
        /* isPresent() method: Checks whether the given Optional
         * Object is empty or not.
         */
        if (GOT.isPresent()) {
            System.out.println("Watching Game of Thrones");
        } else {
            System.out.println("I am getting Bored");
        }
        /* ifPresent() method: It executes only if the given Optional
         * object is non-empty.
         */
        //This will print as the GOT is non-empty
        GOT.ifPresent(s -> System.out.println("Watching GOT is fun!"));
        //This will not print as the nothing is empty
        nothing.ifPresent(s -> System.out.println("I prefer getting bored"));


        System.out.println("===== Optional orElse() and orElseGet() methods =====");
        //orElse() method
        System.out.println(GOT.orElse("Default Value"));
        System.out.println(nothing.orElse("Default Value"));

        //orElseGet() method
        System.out.println(GOT.orElseGet(() -> "Default Value"));
        System.out.println(nothing.orElseGet(() -> "Default Value"));

        System.out.println("===== Optional.map and Optional.flatMap =====");
        System.out.println("toLowerCase:" + GOT.map(String::toLowerCase));
        System.out.println("toLowerCase:" + nothing.map(String::toLowerCase));

        Optional<Optional<String>> anotherOptional = Optional.of(Optional.of("BreakingBad"));
        System.out.println("Value of Optional object" + anotherOptional);

        System.out.println("Optional.map: "
                + anotherOptional.map(gender -> gender.map(String::toUpperCase)));

        //Optional<Optional<String>>    -> flatMap -> Optional<String>
        System.out.println("Optional.flatMap: "
                + anotherOptional.flatMap(gender -> gender.map(String::toUpperCase)));


        System.out.println("===== Optional with filter =====");
        /* Filter returns an empty Optional instance if the output doesn't
         * contain any value, else it returns the Optional object of the
         * given value.
         */
        System.out.println(GOT.filter(s -> s.equals("GAME OF THRONES")));
        System.out.println(GOT.filter(s -> s.equalsIgnoreCase("GAME OF THRONES")));
    }
}
